Skip to content

feat: slot layouts over wrapping operations#196

Merged
arbrandes merged 5 commits intoopenedx:mainfrom
arbrandes:no-slot-wrapping-operation
Mar 23, 2026
Merged

feat: slot layouts over wrapping operations#196
arbrandes merged 5 commits intoopenedx:mainfrom
arbrandes:no-slot-wrapping-operation

Conversation

@arbrandes
Copy link
Contributor

@arbrandes arbrandes commented Mar 19, 2026

Description

Adds an ADR documenting the decision to not implement a widget wrapping operation in frontend-base. The legacy @openedx/frontend-plugin-framework provided a Wrap operation, used notably by frontend-plugin-aspects to toggle sidebar visibility. The ADR explains why the existing layout system is the architecturally preferred alternative, and why a wrapping operation is fundamentally at odds with the slot/layout/widget pipeline.

As part of this decision, useWidgets() is enriched with identity-based filtering helpers (byId(), withoutId(), byRole(), withoutRole()). These methods let layouts selectively render widgets without breaking backwards compatibility — the returned array still renders identically when used as-is. Internally, the widget metadata (ID and role) that was previously stripped before reaching layouts is now preserved and exposed through these helpers.

The (now spruced up) slot showcase gains a new demo showing widgets.byRole() in action: a layout that toggles between all widgets and only those with a "highlighted" role. Two existing showcase options that were passing JSX elements instead of plain strings are also fixed.

Testing

To see this in action, just run npm ci && npm run dev, then navigate to http://apps.local.openedx.io:8080/slots. The go to "Slot with widget filtering by role" and click on "Show only highlighted widgets":

Screencast.From.2026-03-20.12-37-36.mp4

LLM usage notice

Built with assistance from Claude models (mostly Opus 4.6).

@arbrandes
Copy link
Contributor Author

@jsnwesson and @MaxFrank13, would love your thoughts on this, as I suspect you might actually use FPF's wrap operation.

Copy link
Contributor

@holaontiveros holaontiveros left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It makes a lot of sense, I still haven't seen in depth the old system I just check a couple of things on how it worked before so given that many thigns will need to be fully migrated to be compatible with frontend-base maybe we should have some links to some succesful migrations after they start appearing, so everyone can do it easily.

I does look straighforward but depending on how the people look at it some example to wrap their head saround it may be helpful

@arbrandes
Copy link
Contributor Author

@holaontiveros

maybe we should have some links to some succesful migrations after they start appearing, so everyone can do it easily.

Totally. I originally thought about converting frontend-plugin-aspects itself, but unfortunately it targets slots in frontend-app-authoring, which is the last one on the list to be converted to frontend-base.

We'll figure something out in the docs.

Document the decision to not implement a widget wrapping operation in
frontend-base, recommending layout replacements as the architecturally
preferred alternative.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@arbrandes arbrandes force-pushed the no-slot-wrapping-operation branch from 623af19 to 68c7401 Compare March 19, 2026 23:41
arbrandes and others added 2 commits March 19, 2026 20:53
Expose byId(), withoutId(), byRole(), and withoutRole() methods on the
array returned by useWidgets(), enabling layouts to selectively render
widgets by identity without breaking backwards compatibility.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add a ToggleByRoleLayout demo that uses the new widgets.byRole()
helper to toggle between all widgets and only those with a highlighted
role.

Also fix two options values in the showcase that were passing JSX
elements instead of plain strings, causing the options to be ignored
by the type checks in their respective layouts.

Remove outdated wrapping reference from the showcase intro text.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@arbrandes arbrandes changed the title docs: ADR for slot layouts over wrapping operations feat: slot layouts over wrapping operations Mar 20, 2026
Give slot layout authors direct access to the underlying
IdentifiedWidget[] so they can apply arbitrary filtering, sorting,
grouping, or any other operation beyond the built-in helpers.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Contributor

@jesusbalderramawgu jesusbalderramawgu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good, thank you!

Copy link
Contributor

@brian-smith-tcril brian-smith-tcril left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this makes a lot of sense and covers all of the "wrap" examples I can think of. "Modify" is going to be a bigger question, but that's for a separate ADR.

--showcase-indigo-bg: #f8f8fc;
--showcase-teal: #0d9488;
--showcase-teal-bg: #e0f2f1;
--showcase-widget-bg: #f5f5f5;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't love the custom scss here. I especially don't love using custom colors when we have Paragon colors to pull from.

I don't want to block getting the decision landed on the showcase page using custom styles, but it'd be great to have this use Paragon components instead. We can make that a follow-up issue since it feels a bit out-of-scope for this PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. The original bare styling was borderline unusable as a showcase, which is why I sprung for a bare-minimum version... But if it's worth doing, it's worth doing right. (Plus, we're already importing Paragon anyway.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, refactored it to use Paragon styles and components.

Add visual styling to the showcase page and correct route role lookups
in the dev home to use reverse-domain notation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@arbrandes arbrandes force-pushed the no-slot-wrapping-operation branch from cef047b to dd5f15a Compare March 23, 2026 19:40
@arbrandes arbrandes merged commit 47871ac into openedx:main Mar 23, 2026
5 checks passed
@arbrandes arbrandes deleted the no-slot-wrapping-operation branch March 23, 2026 19:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants